#ifndef ARRAY_CPP
#define ARRAY_CPP

#include "Array.h"
#include "ArrayIterador.h"
#include "Puntero.h"
#include <Assert.h>
#include <typeinfo.h>

template<class T>
Array<T>::Array(nat largo)
: MemoryShare(typeid(T).name(), CrearArray(largo), LiberarArray, false)
{
}

template<class T>
Array<T>::Array(const Array<T>& a) : MemoryShare(a)
{
	largo = a.largo;
	arrayReal = a.arrayReal;
}

template<class T>
Array<T>::~Array()
{
}

template<class T>
nat Array<T>::Largo() const
{
	assert(((int) largo) >= 0);
	return largo;
}

template<class T>
T& Array<T>::operator[](nat index) const
{
	assert(index < Largo());
	return arrayReal[index];
}

template<class T>
Array<T>& Array<T>::operator=(const Array<T>& a)
{
	if (&a != this && a.arrayReal != arrayReal)
	{
		largo = a.largo;
		arrayReal = a.arrayReal;
		MemoryShare::operator=((MemoryShare&)a);
	}
	return *this;
}

template<class T>
bool Array<T>::operator==(const Array<T>& a) const
{
	return arrayReal == a.arrayReal;
}

template<class T>
bool Array<T>::operator!=(const Array<T>& a) const
{
	return !(*this == a);
}

template<class T>
Puntero<Iterador<T>> Array<T>::ObtenerIterador() const
{
	return new ArrayIterador<T>(*this);
}

template<class T>
void Array<T>::Copiar(const Array<T>& origen, Array<T>& destino)
{
	Copiar(origen, 0, origen.Largo(), destino, 0);
}

template<class T>
void Array<T>::Copiar(const Array<T>& origen, Array<T>& destino, nat desdeD)
{
	Copiar(origen, 0, origen.Largo(), destino, desdeD);
}

template<class T>
void Array<T>::Copiar(const Array<T>& origen, nat desdeO, Array<T>& destino)
{
	Copiar(origen, desdeO, origen.Largo() - desdeO, destino, 0);
}

template<class T>
void Array<T>::Copiar(const Array<T>& origen, nat desdeO, Array<T>& destino, nat desdeD)
{
	Copiar(origen, desdeO, origen.Largo() - desdeO, destino, desdeD);
}

template<class T>
void Array<T>::Copiar(const Array<T>& origen, nat desdeO, nat largo, Array<T>& destino)
{
	Copiar(origen, desdeO, largo, destino, 0);
}

template<class T>
void Array<T>::Copiar(const Array<T>& origen, nat desdeO, nat largo, Array<T>& destino, nat desdeD)
{
	assert(desdeO + largo <= origen.Largo());
	assert(desdeD + largo <= destino.Largo());
	for (nat i = 0; i < largo; i++)
		destino[desdeD + i] = origen[desdeO + i];
}

template<class T>
void Array<T>::LiberarArray(void* memoria)
{
	T* arrayReal = (T*) memoria;
	delete[] arrayReal;
}

template<class T>
T* Array<T>::CrearArray(nat largo)
{
	this->largo = largo;
	arrayReal = largo == 0 ? NULL : new T[largo];
	return arrayReal;
}

#endif